home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
comm
/
term
/
term34Source.lha
/
termScroll.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-16
|
21KB
|
961 lines
/*
** termScroll.c
**
** Support routines for optimized screen scrolling.
**
** Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#include "termGlobal.h"
/* ScrollLineRectFill():
*
* Fill a rectangular portion of the window raster with the help
* of the scrolling information.
*/
VOID __regargs
ScrollLineRectFill(struct RastPort *RPort,WORD MinX,WORD MinY,WORD MaxX,WORD MaxY)
{
if(RPort -> BitMap -> Depth > 1)
{
if(MinX < MaxX)
{
/* Is there anything on the screen at all? */
if(ScrollLineFirst <= ScrollLineLast)
{
if(UseMasking)
{
WORD ScrollLineMask = 0,
ScrollLineLeft = 32767,
ScrollLineRight = 0,
Temp,
i;
/* Determine screen colour mask. */
for(i = MinY / TextFontHeight ; i <= MaxY / TextFontHeight ; i++)
{
if(ScrollLines[i] . Width)
{
if((Temp = ScrollLines[i] . Left * ScrollLines[i] . Width) < ScrollLineLeft)
ScrollLineLeft = Temp;
if((Temp = (ScrollLines[i] . Right * ScrollLines[i] . Width) - 1) > ScrollLineRight)
ScrollLineRight = Temp;
ScrollLineMask |= ScrollLines[i] . ColourMask;
}
}
/* Wrap the bits. */
ScrollLineMask &= DepthMask;
/* Did we get a sensible colour? */
if(ScrollLineMask && ScrollLineLeft <= ScrollLineRight)
{
/* Determine new left margin. */
if(ScrollLineLeft > MinX)
MinX = ScrollLineLeft;
/* Determine new right margin. */
if(ScrollLineRight < MaxX)
MaxX = ScrollLineRight;
/* Determine new top line margin. */
if((Temp = MUL_Y(ScrollLineFirst)) > MinY)
MinY = Temp;
/* Determine new bottom line margin. */
if((Temp = MUL_Y(ScrollLineLast + 1) - 1) < MaxY)
MaxY = Temp;
/* Set the colour mask. */
SetWrMsk(RPort,ScrollLineMask);
/* Add margin for italics or boldface. */
if(MaxX == ScrollLineRight)
MaxX += FontRightExtend;
}
}
else
{
WORD ScrollLineLeft = 32767,
ScrollLineRight = 0,
Temp,
i;
/* Determine screen colour mask. */
for(i = MinY / TextFontHeight ; i <= MaxY / TextFontHeight ; i++)
{
if(ScrollLines[i] . Width)
{
if((Temp = ScrollLines[i] . Left * ScrollLines[i] . Width) < ScrollLineLeft)
ScrollLineLeft = Temp;
if((Temp = (ScrollLines[i] . Right * ScrollLines[i] . Width) - 1) > ScrollLineRight)
ScrollLineRight = Temp;
}
}
/* Did we get a sensible colour? */
if(ScrollLineLeft <= ScrollLineRight)
{
/* Determine new left margin. */
if(ScrollLineLeft > MinX)
MinX = ScrollLineLeft;
/* Determine new right margin. */
if(ScrollLineRight < MaxX)
MaxX = ScrollLineRight;
/* Determine new top line margin. */
if((Temp = MUL_Y(ScrollLineFirst)) > MinY)
MinY = Temp;
/* Determine new bottom line margin. */
if((Temp = MUL_Y(ScrollLineLast + 1) - 1) < MaxY)
MaxY = Temp;
/* Add margin for italics or boldface. */
if(MaxX == ScrollLineRight)
MaxX += FontRightExtend;
}
}
}
}
}
/* And clear the raster. */
if(MinX < MaxX && MinY < MaxY)
RectFill(RPort,WindowLeft + MinX,WindowTop + MinY,WindowLeft + MaxX,WindowTop + MaxY);
}
/* ScrollLineRaster():
*
* Scroll the window raster with the help
* of the scrolling information.
*/
VOID __regargs
ScrollLineRaster(struct RastPort *RPort,WORD DeltaX,WORD DeltaY,WORD MinX,WORD MinY,WORD MaxX,WORD MaxY,BYTE Smooth)
{
if(RPort -> BitMap -> Depth > 1)
{
if(MinX < MaxX)
{
if(UseMasking)
{
WORD ScrollLineMask;
/* Are we to scroll a line in horizontal direction? If so, use the
* colour mask of the current line.
*/
if(DeltaX)
{
/* Set the colour mask. */
if(ScrollLineMask = ScrollLines[CursorY] . ColourMask & DepthMask)
SetWrMsk(RPort,ScrollLineMask);
}
else
{
/* Any data on screen worth scrolling? */
if(ScrollLineFirst <= ScrollLineLast)
{
WORD Temp,First,Last,SaveMinY = MinY / TextFontHeight,SaveMaxY = MaxY / TextFontHeight,ScrollLineLeft = 32767,ScrollLineRight = 0,i;
/* Reset colourmask. */
ScrollLineMask = 0;
/* Build both the colour mask and the margins. */
for(i = MinY / TextFontHeight ; i <= MaxY / TextFontHeight ; i++)
{
if(ScrollLines[i] . Width)
{
if((Temp = ScrollLines[i] . Left * ScrollLines[i] . Width) < ScrollLineLeft)
ScrollLineLeft = Temp;
if((Temp = (ScrollLines[i] . Right * ScrollLines[i] . Width) - 1) > ScrollLineRight)
ScrollLineRight = Temp;
ScrollLineMask |= ScrollLines[i] . ColourMask;
}
}
/* Wrap the bits. */
ScrollLineMask &= DepthMask;
/* Sensible results? */
if(ScrollLineMask && ScrollLineLeft <= ScrollLineRight)
{
/* Determine new left margin. */
if(ScrollLineLeft > MinX)
MinX = ScrollLineLeft;
/* Determine new right margin. */
if(ScrollLineRight < MaxX)
MaxX = ScrollLineRight;
/* Scroll down or up? */
if(DeltaY < 0)
{
/* So we are to scroll down, find the first
* blank line if any.
*/
if((Temp = MUL_Y(ScrollLineFirst)) > MinY)
MinY = Temp;
/* Find the last blank lines if any. */
if((Temp = MUL_Y(ScrollLineLast + 1) - DeltaY - 1) < MaxY)
MaxY = Temp;
/* Determine margins and the like... */
Last = (MaxY + 1) / TextFontHeight;
First = Last - ((MaxY - MinY + TextFontHeight + DeltaY) / TextFontHeight);
Temp = (-DeltaY) / TextFontHeight;
/* Move the scroll line info up. */
for(i = Last - 1 ; i >= First ; i--)
ScrollLines[i] = ScrollLines[i - Temp];
/* Clear the remaining lines. */
for(i = First - Temp ; i < First ; i++)
{
ScrollLines[i] . Left = 32767;
ScrollLines[i] . Right = 0;
ScrollLines[i] . ColourMask = 0;
ScrollLines[i] . Width = 0;
}
/* Is the first line we were working
* on the first line of the whole display?
* If so, update the line marker.
*/
if(!SaveMinY)
ScrollLineFirst += Temp;
/* Now take a look at the last line.
* If the last line we were working
* on is in fact the last line of the
* display, update the line marker.
*/
if(SaveMaxY == LastLine)
{
ScrollLineLast += Temp;
if(ScrollLineLast > LastLine)
ScrollLineLast = LastLine;
}
}
else
{
/* So we are to scroll up, find the last
* blank line if any.
*/
if((Temp = MUL_Y(ScrollLineLast + 1) - 1) < MaxY)
MaxY = Temp;
/* Find the first blank lines if any. */
if((Temp = MUL_Y(ScrollLineFirst) - DeltaY) > MinY)
MinY = Temp;
/* Determine margins and the like... */
First = MinY / TextFontHeight;
Last = ((MaxY - MinY + TextFontHeight - DeltaY) / TextFontHeight);
Temp = DeltaY / TextFontHeight;
/* Move the scroll line info down. */
for(i = First ; i < First + Last ; i++)
ScrollLines[i] = ScrollLines[i + Temp];
/* Clear the remaining lines. */
for(i = First + Last ; i < First + Last + Temp ; i++)
{
ScrollLines[i] . Left = 32767;
ScrollLines[i] . Right = 0;
ScrollLines[i] . ColourMask = 0;
ScrollLines[i] . Width = 0;
}
/* Decrease number of last line. */
if(SaveMaxY == LastLine)
{
if(ScrollLineLast > Temp)
ScrollLineLast -= Temp;
else
ScrollLineLast = 0;
}
/* Decrease number of first line. */
if(!SaveMinY)
{
if(ScrollLineFirst > Temp)
ScrollLineFirst -= Temp;
else
ScrollLineFirst = 0;
}
}
/* Adapt possible changes in the lines for first and last line. */
while(ScrollLineFirst < RasterHeight)
{
if(ScrollLines[ScrollLineFirst] . Left > ScrollLines[ScrollLineFirst] . Right)
ScrollLineFirst++;
else
break;
}
while(ScrollLineLast > 0)
{
if(ScrollLines[ScrollLineLast] . Left > ScrollLines[ScrollLineLast] . Right)
ScrollLineLast--;
else
break;
}
/* Set the colour mask. */
SetWrMsk(RPort,ScrollLineMask);
/* Add margin for italics or boldface. */
if(MaxX == ScrollLineRight)
MaxX += FontRightExtend;
}
}
}
}
else
{
/* Are we to scroll a line in horizontal direction? If so, use the
* colour mask of the current line.
*/
if(!DeltaX)
{
/* Any data on screen worth scrolling? */
if(ScrollLineFirst <= ScrollLineLast)
{
WORD Temp,First,Last,SaveMinY = MinY / TextFontHeight,SaveMaxY = MaxY / TextFontHeight,ScrollLineLeft = 32767,ScrollLineRight = 0,i;
/* Build both the colour mask and the margins. */
for(i = MinY / TextFontHeight ; i <= MaxY / TextFontHeight ; i++)
{
if(ScrollLines[i] . Width)
{
if((Temp = ScrollLines[i] . Left * ScrollLines[i] . Width) < ScrollLineLeft)
ScrollLineLeft = Temp;
if((Temp = (ScrollLines[i] . Right * ScrollLines[i] . Width) - 1) > ScrollLineRight)
ScrollLineRight = Temp;
}
}
/* Sensible results? */
if(ScrollLineLeft <= ScrollLineRight)
{
/* Determine new left margin. */
if(ScrollLineLeft > MinX)
MinX = ScrollLineLeft;
/* Determine new right margin. */
if(ScrollLineRight < MaxX)
MaxX = ScrollLineRight;
/* Scroll down or up? */
if(DeltaY < 0)
{
/* So we are to scroll down, find the first
* blank line if any.
*/
if((Temp = MUL_Y(ScrollLineFirst)) > MinY)
MinY = Temp;
/* Find the last blank lines if any. */
if((Temp = MUL_Y(ScrollLineLast + 1) - DeltaY - 1) < MaxY)
MaxY = Temp;
/* Determine margins and the like... */
Last = (MaxY + 1) / TextFontHeight;
First = Last - ((MaxY - MinY + TextFontHeight + DeltaY) / TextFontHeight);
Temp = (-DeltaY) / TextFontHeight;
/* Move the scroll line info up. */
for(i = Last - 1 ; i >= First ; i--)
ScrollLines[i] = ScrollLines[i - Temp];
/* Clear the remaining lines. */
for(i = First - Temp ; i < First ; i++)
{
ScrollLines[i] . Left = 32767;
ScrollLines[i] . Right = 0;
ScrollLines[i] . Width = 0;
}
/* Is the first line we were working
* on the first line of the whole display?
* If so, update the line marker.
*/
if(!SaveMinY)
ScrollLineFirst += Temp;
/* Now take a look at the last line.
* If the last line we were working
* on is in fact the last line of the
* display, update the line marker.
*/
if(SaveMaxY == LastLine)
{
ScrollLineLast += Temp;
if(ScrollLineLast > LastLine)
ScrollLineLast = LastLine;
}
}
else
{
/* So we are to scroll up, find the last
* blank line if any.
*/
if((Temp = MUL_Y(ScrollLineLast + 1) - 1) < MaxY)
MaxY = Temp;
/* Find the first blank lines if any. */
if((Temp = MUL_Y(ScrollLineFirst) - DeltaY) > MinY)
MinY = Temp;
/* Determine margins and the like... */
First = MinY / TextFontHeight;
Last = ((MaxY - MinY + TextFontHeight - DeltaY) / TextFontHeight);
Temp = DeltaY / TextFontHeight;
/* Move the scroll line info down. */
for(i = First ; i < First + Last ; i++)
ScrollLines[i] = ScrollLines[i + Temp];
/* Clear the remaining lines. */
for(i = First + Last ; i < First + Last + Temp ; i++)
{
ScrollLines[i] . Left = 32767;
ScrollLines[i] . Right = 0;
ScrollLines[i] . Width = 0;
}
/* Decrease number of last line. */
if(SaveMaxY == LastLine)
{
if(ScrollLineLast > Temp)
ScrollLineLast -= Temp;
else
ScrollLineLast = 0;
}
/* Decrease number of first line. */
if(!SaveMinY)
{
if(ScrollLineFirst > Temp)
ScrollLineFirst -= Temp;
else
ScrollLineFirst = 0;
}
}
/* Adapt possible changes in the lines for first and last line. */
while(ScrollLineFirst < RasterHeight)
{
if(ScrollLines[ScrollLineFirst] . Left > ScrollLines[ScrollLineFirst] . Right)
ScrollLineFirst++;
else
break;
}
while(ScrollLineLast > 0)
{
if(ScrollLines[ScrollLineLast] . Left > ScrollLines[ScrollLineLast] . Right)
ScrollLineLast--;
else
break;
}
/* Add margin for italics or boldface. */
if(MaxX == ScrollLineRight)
MaxX += FontRightExtend;
}
}
}
}
}
}
/* And scroll the raster. */
if(MinX < MaxX && MinY < MaxY)
{
LONG OldPen;
MinX += WindowLeft;
MaxX += WindowLeft;
MinY += WindowTop;
MaxY += WindowTop;
/* Non-standard background colour? */
if((OldPen = ReadBPen(RPort)) != MappedPens[0][0])
{
SetBPen(RPort,MappedPens[0][0]);
if(Smooth && DeltaY)
{
WORD Lines = DeltaY / 2;
if(Lines > 0)
{
while(Lines--)
{
WaitTOF();
ScrollRaster(RPort,0,2,MinX,MinY,MaxX,MaxY);
}
}
else
{
while(Lines++)
{
WaitTOF();
ScrollRaster(RPort,0,-2,MinX,MinY,MaxX,MaxY);
}
}
}
else
ScrollRaster(RPort,DeltaX,DeltaY,MinX,MinY,MaxX,MaxY);
SetBPen(RPort,OldPen);
}
else
{
if(Smooth && DeltaY)
{
WORD Lines = DeltaY / 2;
if(Lines > 0)
{
while(Lines--)
{
WaitTOF();
ScrollRaster(RPort,0,2,MinX,MinY,MaxX,MaxY);
}
}
else
{
while(Lines++)
{
WaitTOF();
ScrollRaster(RPort,0,-2,MinX,MinY,MaxX,MaxY);
}
}
}
else
ScrollRaster(RPort,DeltaX,DeltaY,MinX,MinY,MaxX,MaxY);
}
}
}
/* ScrollLineEraseScreen(BYTE Mode):
*
* Erase a part of the screen.
*/
VOID __regargs
ScrollLineEraseScreen(BYTE Mode)
{
if(RPort -> BitMap -> Depth > 1)
{
WORD i;
switch(Mode)
{
/* Erase from first line to current cursor line (inclusive). */
case 1: ScrollLineFirst = CursorY;
/* Reset the lines. */
for(i = 0 ; i < CursorY ; i++)
{
ScrollLines[i] . Left = 32767;
ScrollLines[i] . Right = 0;
ScrollLines[i] . ColourMask = 0;
ScrollLines[i] . Width = 0;
}
ScrollLines[CursorY] . Left = CursorX + 1;
if(ScrollLines[CursorY] . Right < ScrollLines[CursorY] . Left)
{
ScrollLines[CursorY] . Left = 32767;
ScrollLines[CursorY] . Right = 0;
}
break;
/* Erase entire screen. */
case 2: for(i = 0 ; i < RasterHeight ; i++)
{
ScrollLines[i] . Left = 32767;
ScrollLines[i] . Right = 0;
ScrollLines[i] . ColourMask = 0;
ScrollLines[i] . Width = 0;
}
ScrollLineFirst = 32767;
ScrollLineLast = 0;
break;
/* Erase from current cursor position to end of screen. */
default:for(i = CursorY + 1 ; i < RasterHeight ; i++)
{
ScrollLines[i] . Left = 32767;
ScrollLines[i] . Right = 0;
ScrollLines[i] . ColourMask = 0;
ScrollLines[i] . Width = 0;
}
if(CursorX)
{
ScrollLines[CursorY] . Right = CursorX;
if(ScrollLines[CursorY] . Right < ScrollLines[CursorY] . Left)
{
ScrollLines[CursorY] . Left = 32767;
ScrollLines[CursorY] . Right = 0;
}
}
else
{
ScrollLines[CursorY] . Left = 32767;
ScrollLines[CursorY] . Right = 0;
}
/* Cleared the entire screen? */
if(CursorY)
ScrollLineLast = CursorY;
else
{
ScrollLineFirst = 32767;
ScrollLineLast = 0;
}
break;
}
/* Adapt possible changes in the lines for first and last line. */
while(ScrollLineFirst < RasterHeight)
{
if(ScrollLines[ScrollLineFirst] . Left > ScrollLines[ScrollLineFirst] . Right)
ScrollLineFirst++;
else
break;
}
while(ScrollLineLast > 0)
{
if(ScrollLines[ScrollLineLast] . Left > ScrollLines[ScrollLineLast] . Right)
ScrollLineLast--;
else
break;
}
}
}
/* ScrollLineEraseLine(BYTE Mode):
*
* Erase parts of the current cursor line.
*/
VOID __regargs
ScrollLineEraseLine(BYTE Mode)
{
if(RPort -> BitMap -> Depth > 1)
{
switch(Mode)
{
/* Erase from left margin to current cursor position (inclusive). */
case 1: ScrollLines[CursorY] . Left = CursorX + 1;
break;
/* Erase entire line. */
case 2: ScrollLines[CursorY] . Left = 32767;
ScrollLines[CursorY] . Right = 0;
break;
/* Erase from current cursor position towards end of line. */
default:if(CursorX)
ScrollLines[CursorY] . Right = CursorX;
else
{
ScrollLines[CursorY] . Left = 32767;
ScrollLines[CursorY] . Right = 0;
}
break;
}
/* Adapt possible changes in the lines for first and last line. */
while(ScrollLineFirst < RasterHeight)
{
if(ScrollLines[ScrollLineFirst] . Left > ScrollLines[ScrollLineFirst] . Right)
ScrollLineFirst++;
else
break;
}
while(ScrollLineLast > 0)
{
if(ScrollLines[ScrollLineLast] . Left > ScrollLines[ScrollLineLast] . Right)
ScrollLineLast--;
else
break;
}
}
}
/* ScrollLineEraseCharacters(WORD Chars):
*
* Erase a number of characters in the current cursor line.
*/
VOID __regargs
ScrollLineEraseCharacters(WORD Chars)
{
if(RPort -> BitMap -> Depth > 1)
{
/* Any characters to erase? */
if(ScrollLines[CursorY] . Right)
ScrollLines[CursorY] . Right -= Chars;
}
}
/* ScrollLineShiftChar(WORD Size):
*
* Shift the characters following the current cursor position
* Size characters to the right.
*/
VOID __regargs
ScrollLineShiftChar(WORD Size)
{
if(RPort -> BitMap -> Depth > 1)
{
/* Any characters to scroll? */
if(ScrollLines[CursorY] . Right > 0)
ScrollLines[CursorY] . Right += Size;
}
}
/* ScrollLinePutString(WORD Length):
*
* Update the line info according to the length of a string
* to be printed.
*/
VOID __regargs
ScrollLinePutString(WORD Length)
{
if(RPort -> BitMap -> Depth > 1)
{
LONG Width;
/* Which scale is the font we are currently using? */
if(RasterAttr[CursorY] >= SCALE_ATTR_TOP2X)
{
/* Valid length? */
if(CursorX + Length >= RasterWidth / 2)
Length = (RasterWidth / 2) - CursorX;
/* Double width. */
Width = TextFontWidth * 2;
}
else
{
if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
{
/* Valid length? */
if(CursorX + Length >= RasterWidth * 2)
Length = (RasterWidth * 2) - CursorX;
/* Half width. */
Width = TextFontWidth / 2;
}
else
{
/* Valid length? */
if(CursorX + Length >= RasterWidth)
Length = RasterWidth - CursorX;
/* Normal width. */
Width = TextFontWidth;
}
}
/* Sensible value? */
if(Length > 0)
{
if(UseMasking)
{
struct ScrollLineInfo *Alias = &ScrollLines[CursorY];
/* Update line colour mask. */
Alias -> ColourMask |= ReadAPen(RPort) | ReadBPen(RPort);
/* Update font scale. */
Alias -> Width = Width;
/* Set write mask (will affect Text() since it is called
* after this routine has finished.
*/
SetWrMsk(RPort,Alias -> ColourMask);
/* Update right margin. */
if(CursorX < Alias -> Left)
Alias -> Left = CursorX;
/* Update left margin. */
if(CursorX + Length > Alias -> Right)
Alias -> Right = CursorX + Length;
/* Update topmost line. */
if(CursorY < ScrollLineFirst)
ScrollLineFirst = CursorY;
/* Update bottommost line. */
if(CursorY > ScrollLineLast)
ScrollLineLast = CursorY;
}
else
{
struct ScrollLineInfo *Alias = &ScrollLines[CursorY];
/* Update font scale. */
Alias -> Width = Width;
/* Update right margin. */
if(CursorX < Alias -> Left)
Alias -> Left = CursorX;
/* Update left margin. */
if(CursorX + Length > Alias -> Right)
Alias -> Right = CursorX + Length;
/* Update topmost line. */
if(CursorY < ScrollLineFirst)
ScrollLineFirst = CursorY;
/* Update bottommost line. */
if(CursorY > ScrollLineLast)
ScrollLineLast = CursorY;
}
}
}
}